﻿using FaissOperation.FaissIndex;
using FaissOperation.FaissIndexFlat;
using FaissOperation.Interface;
using FaissOperation.LiteVectorCollection;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO.Packaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FaissOperation
{
    /// <summary>
    /// 集合操作的管理器，负责向量集合的创建、删除和查询等操作。
    /// </summary>
    public class CollectionManager
    {
        private static CollectionManager _instance;

        private ConcurrentDictionary<string, CollectionPackage> _collections = new();

        /// <summary>
        ///  获取集合管理器的单例实例。
        /// </summary>
        public static CollectionManager Instance
        {
            get
            {
                if (_instance == null)
                {
                    _instance = new CollectionManager();
                }
                return _instance;
            }
        }

        private CollectionManager()
        {
            // 单件
        }


        /// <summary>
        /// 添加一个新的向量集合，如果Key已经存在，那就不在添加，而是返回已存在的集合。
        /// </summary>
        /// <param name="metaData">向量集合的元数据</param>
        /// <param name="key">集合的唯一标识</param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException">不支持的类型</exception>
        public IVectorCollection<float[]> AddCollection(string key, CollectionMetaData metaData)
        {
            if (_collections.ContainsKey(key))
            {
                return _collections[key].Collection;
            }

            IVectorCollection<float[]> collection = metaData.CollectionType switch
            {
                CollectionType.Flat => new FlatVectorCollection(),
                CollectionType.IVF => new IVFVectorCollection(),
                CollectionType.Lite => new LiteVectorIndex(),
                _ => throw new NotSupportedException($"集合类型 '{metaData.CollectionType}' 无法识别。")
            };

            collection.Dimension = metaData.Dimension;
            collection.MetricTypeInUse = metaData.MetricType;
            collection.NormalizeOnAddAndQuery = metaData.NormalizeOnAdd;

            var package = new CollectionPackage()
            {
                Collection = collection,
                Meta = metaData
            };

            _collections[key] = package;

            return collection;
        }

        /// <summary>
        /// 删除一个向量集合，不存在的话就不做任何操作。
        /// </summary>
        /// <param name="key">向量集合的ID</param>
        public void RemoveCollection(string key)
        {
            CollectionPackage pkg = null;

            if (_collections.ContainsKey(key))
            {
                _collections.Remove(key, out pkg);
            }

            if (pkg != null)
            {
                pkg.Collection.Destory();
            }
        }

        /// <summary>
        /// 获取向量集合，如果不存在则抛出异常。
        /// </summary>
        /// <param name="key">向量集合的ID</param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException">指定的集合不存在</exception>
        public IVectorCollection<float[]> GetCollection(string key)
        {
            if (_collections.ContainsKey(key))
            {
                return _collections[key].Collection;
            }
            else {
                throw new InvalidOperationException($"没有找到名为 '{key}' 的集合。");

            }
        }

        /// <summary>
        /// 获取向量集合的元数据，如果不存在则抛出异常。
        /// </summary>
        /// <param name="key">向量集合的ID</param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException">指定的集合不存在</exception>
        public CollectionMetaData GetMeta(string key) {
            if (_collections.ContainsKey(key))
            {
                return _collections[key].Meta;
            }
            else
            {
                throw new InvalidOperationException($"没有找到名为 '{key}' 的集合。");

            }

        }

        /// <summary>
        /// 检查集合是否已经被加载
        /// </summary>
        /// <param name="key">向量的唯一标识</param>
        /// <returns></returns>
        public bool CollectionExists(string key)
        {
            return _collections.ContainsKey(key);
        }

        public int Count() { 
        
            return _collections.Count;
        }

        public int Count(CollectionType type) { 
            return _collections.Where(d=>d.Value.Meta.CollectionType == type).Count();
        }
    }

    public class CollectionPackage
    {

        public CollectionMetaData Meta { get; set; }

        public IVectorCollection<float[]> Collection { get; set; }
    }

    public class CollectionMetaData
    {

        public CollectionMetaData(CollectionType type, int dimension = 1024, bool normalizeOnAdd = false, MetricType metricType = MetricType.L2)
        {
            CollectionType = type;
            Dimension = dimension;
            NormalizeOnAdd = normalizeOnAdd;
            MetricType = metricType;
        }

        public int Dimension { get; set; }

        public bool NormalizeOnAdd { get; set; }

        public MetricType MetricType { get; set; }

        public CollectionType CollectionType { get; set; }
    }

}
